from django.shortcuts import get_object_or_404, render
from .models import EachTest, EachTestType
from django.core.paginator import Paginator
from django.db.models import Count
from Pra_Show.pra_algorithm import cacu_res
import numpy as np

test_number_each_page = 5


def common(tests_all_list, request):
    pa = Paginator(tests_all_list, test_number_each_page)
    page_num = request.GET.get('page', 1)  # 获取url的页码参数
    page_of_tests = pa.get_page(page_num)
    current_page_num = page_of_tests.number  # 获取当前页码
    # 获取当前页码前后各两页
    page_range = list(range(max(current_page_num - 2, 1), current_page_num)) + \
                 list(range(current_page_num, min(current_page_num + 2, pa.num_pages) + 1))
    if page_range[0] - 1 >= 2:
        page_range.insert(0, "...")
    if pa.num_pages - page_range[-1] >= 2:
        page_range.append("...")
    if page_range[0] != 1:
        page_range.insert(0, 1)
    if page_range[-1] != pa.num_pages:
        page_range.append(pa.num_pages)

    test_dates = EachTest.objects.dates('created_time', 'month', order="DESC")
    test_dates_dict = dict()
    for test_date in test_dates:
        test_count = EachTest.objects.filter(created_time__year=test_date.year,
                                         created_time__month=test_date.month).count()
        test_dates_dict[test_date] = test_count
    # annotate也可以

    context = dict()
    context['tests'] = page_of_tests.object_list
    context['page_of_tests'] = page_of_tests
    context['test_types'] = EachTestType.objects.annotate(test_count=Count('eachtest'))
    context['page_range'] = page_range
    context['test_dates'] = test_dates_dict
    return context


def random_walker(min_num, max_num, page_queen_len):
    num = 1
    res = []
    l = np.random.randint(min_num, max_num, page_queen_len)
    new_num = np.random.choice(l)
    res.append(new_num)
    while num < page_queen_len:
        new_num = np.random.choice(l)
        if new_num == res[num-1]:
            continue
        else:
            res.append(new_num)
            num += 1
    return res


# Create your view_pakage here.
def test_list(request):
    tests_all_list = EachTest.objects.all()
    context = dict()
    context = common(tests_all_list, request)
    return render(request, 'test_list.html', context)


def test_detail(request, test_id):
    # 如果当前request是get，去查看实验的状态是0还是1，0：显示让用户显示超参数并启动页面
    # 1：显示结果
    # 如果当前request是post,说明用户想要开始实验，获取用户所给的参数并开始实验，得到实验结果后
    # 将数据存到数据库，并修改状态为1
    test = get_object_or_404(EachTest, id=test_id)
    context = dict()
    if request.method == 'POST':
        test_type = request.POST.get('test_type', '')
        physical_block = request.POST.get('block_num', '')
        page_queen_len = request.POST.get('page_queen_len', '')
        page_cf_num = request.POST.get('page_cf_num', '')
        # test_type = request.POST.get('test_type', '')
        test.physical_block = physical_block
        test.page_queen_len = page_queen_len
        test.page_cf_num = page_cf_num
        random_a = random_walker(0, int(page_cf_num), int(page_queen_len))
        context['random_a'] = random_a
        if test_type == "Compare_Algorithm":
            page_fault_ratef, _, _, _ = cacu_res("FIFO", physical_block, page_queen_len, page_cf_num, random_a)
            page_fault_ratel, _, _, _ = cacu_res("LRU", physical_block, page_queen_len, page_cf_num, random_a)
            page_fault_rateo, _, _, _ = cacu_res("OPT", physical_block, page_queen_len, page_cf_num, random_a)
            context['page_fault_ratef'] = page_fault_ratef
            context['page_fault_ratel'] = page_fault_ratel
            context['page_fault_rateo'] = page_fault_rateo
        else:
            page_fault_rate, if_lack, block_list, in_list = \
                cacu_res(test_type, physical_block, page_queen_len, page_cf_num, random_a)
            test.page_fault_rate = page_fault_rate
            context['page_fault_rate'] = page_fault_rate
            context['if_lack'] = if_lack
            context['block_list'] = block_list
            context['in_list'] = in_list
        test.show_res_bool = 1
    else:
        test.show_res_bool = 0
    test.save()
    context['test'] = test
    return render(request, 'test_detail.html', context)


def test_comp(request):
    context = dict()
    pfr_fifo = []
    pfr_lru = []
    pfr_opt = []
    if request.method == 'POST':
        show_res_bool = 1
        block_num_min = request.POST.get('block_num_min', '')
        block_num_max = request.POST.get('block_num_max', '')
        page_queen_len = request.POST.get('page_queen_len', '')
        page_cf_num = request.POST.get('page_cf_num', '')
        random_a = random_walker(0, int(page_cf_num), int(page_queen_len))
        context['random_a'] = random_a
        block_num_list = []
        context['block_num_min'] = block_num_min
        context['block_num_max'] = block_num_max
        context['page_queen_len'] = page_queen_len
        context['page_cf_num'] = page_cf_num
        for i in range(int(block_num_min), int(block_num_max)+1):
            block_num_list.append(i)
            page_fault_ratef, _, _, _ = cacu_res("FIFO", i, page_queen_len, page_cf_num, random_a)
            pfr_fifo.append(page_fault_ratef)
            page_fault_ratel, _, _, _ = cacu_res("LRU", i, page_queen_len, page_cf_num, random_a)
            pfr_lru.append(page_fault_ratel)
            page_fault_rateo, _, _, _ = cacu_res("OPT", i, page_queen_len, page_cf_num, random_a)
            pfr_opt.append(page_fault_rateo)
        context['pfr_fifo'] = pfr_fifo
        context['pfr_lru'] = pfr_lru
        context['pfr_opt'] = pfr_opt
        context['block_num_list'] = block_num_list
    else:
        show_res_bool = 0
    context['show_res_bool'] = show_res_bool

    return render(request, 'test_comp.html', context)


def test_alone(request):
    context = dict()
    pfr_list = []
    context['show_res_bool'] = 0
    if request.method == 'POST':
        context['show_res_bool'] = 1
        test_type = (request.POST.get('test_type', '')).upper()
        block_num_min = request.POST.get('block_num_min', '')
        block_num_max = request.POST.get('block_num_max', '')
        page_queen_len = request.POST.get('page_queen_len', '')
        page_cf_num = request.POST.get('page_cf_num', '')
        # random_a = np.random.randint(0, int(page_cf_num), int(page_queen_len))
        random_a = random_walker(0, int(page_cf_num), int(page_queen_len))
        context['random_a'] = random_a
        block_num_list = []
        context['test_type'] = test_type
        context['block_num_min'] = block_num_min
        context['block_num_max'] = block_num_max
        context['page_queen_len'] = page_queen_len
        context['page_cf_num'] = page_cf_num
        for i in range(int(block_num_min), int(block_num_max) + 1):
            block_num_list.append(i)
            page_fault_rate, _, _, _ = cacu_res(test_type, i, page_queen_len, page_cf_num, random_a)
            pfr_list.append(page_fault_rate)
        context['block_num_list'] = block_num_list
        context['pfr_list'] = pfr_list

    print(pfr_list)
    return render(request, 'test_alone.html', context)